package com.scanx.conf;

import com.scanx.App;
import com.scanx.enums.ExceptionCode;
import com.scanx.exception.ScanException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.Set;

/**
 * @author alpha.
 * @className CommonConf
 * @date 2024/2/6 11:20
 */
@Data
@Slf4j
public class CommonConf {

    public static String VERSION;                       //工具版本
    public static String START_PATH;                    //扫描开始路径
    public static int DIRECTORY_SCAN_THREAD_SIZE;       //目录扫描线程数
    public static int SENSITIVE_ANALYZE_THREAD_SIZE;    //敏感分析线程数
    public static int IGNORE_FILE_MAX_SIZE;             //忽略扫描文件大小阈值
    public static List<String> IGNORE_PATHS;             //免扫描路径
    public static List<String> IGNORE_SUFFIX;            //忽略文件后缀

    /**
     * 公共配置初始化
     */
    public static void init() {
        try {
            Properties properties = getProperties();
            VERSION = getConf(properties, "scanX.version");
            START_PATH = getConf(properties, "scanX.start.path");
            IGNORE_PATHS = getConfs(properties, "scanX.ignore.paths");
            IGNORE_SUFFIX = getConfs(properties, "scanX.ignore.file.suffix");
            DIRECTORY_SCAN_THREAD_SIZE = getConfOrDefault(properties, "scanX.directory.scan.thread.size", 8);
            SENSITIVE_ANALYZE_THREAD_SIZE = getConfOrDefault(properties, "scanX.sensitive.analyze.thread.size", 8);
            IGNORE_FILE_MAX_SIZE = getConfOrDefault(properties, "scanX.ignore.file.max.size", -1);
        } catch (Exception e) {
            throw new ScanException(ExceptionCode.CONF_INIT_ERROR, "配置初始化失败", e);
        }
    }

    /**
     * 获取配置值或默认值
     *
     * @param properties 配置
     * @param key        配置key
     * @param defaultV   默认值
     * @return 配置值
     */
    private static int getConfOrDefault(Properties properties, String key, int defaultV) {
        Object value = properties.getOrDefault(key, defaultV);
        value = (null == value || "".equals(value)) ? defaultV : value;
        log.info("{}  ==>  {}", key, value);
        return Integer.parseInt(value.toString());
    }

    /**
     * 获取忽略扫描的路径
     *
     * @param properties 配置
     * @return 忽略路径集合
     */
    private static List<String> getConfs(Properties properties, String key) {
        String paths = properties.getProperty(key);
        if (StringUtils.isBlank(paths)) {
            log.warn("{}  ==>  未配置", key);
            return null;
        }
        List<String> pathList = Arrays.asList(paths.split(","));
        log.info("{}  ==>  {}", key, pathList);
        return pathList;
    }

    /**
     * 获取配置值
     *
     * @param properties 配置
     * @param key        配置key
     * @return 配置值
     */
    private static String getConf(Properties properties, String key) {
        String property = properties.getProperty(key);
        log.info("{}  ==>  {}", key, property);
        return property;
    }


    /**
     * 获取配置
     *
     * @return 配置
     */
    private static Properties getProperties() throws IOException {
        Properties properties = new Properties();
        String dir = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParent();
        Path path = new File(dir + File.separator + "application.properties").toPath();
        InputStream confStream;

        //优先使用jar包同级别目录配置文件
        if (path.toFile().exists()) {
            confStream = Files.newInputStream(path);
        } else {
            confStream = App.class.getResourceAsStream(File.separator + "application.properties");
        }
        properties.load(confStream);

        String version = properties.getProperty("scanX.version");
        if (StringUtils.isBlank(version)) {
            throw new ScanException("工具版本未找到");
        }
        log.info("当前工具版本：{}", version);
        return properties;
    }


}
